#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h> // For malloc_usable_size

#include <cstdint>

void print_chunk_info(void *ptr, int index) {
    size_t *chunk = (size_t *)ptr - 2;  // 获取 chunk 头
    printf("index:%d, Chunk addr: %p\n", index, chunk);
    
    size_t size = chunk[1] & ~0x7;
    printf("    size: %lu\n", size);

    size_t flags = chunk[1] & 0x7;
    if (flags & 0x1) {
        printf("    PREV_INUSE is set\n");
    } else {
        printf("    prev_size: %lu\n", chunk[0]);
    }
    if (flags & 0x2) {
        printf("    IS_MMAPPED is set\n");
    }
    if (flags & 0x4) {
        printf("    NON_MAIN_ARENA  is set\n");
    }
}

void *ptr[16] = {0};
int flag[16] = {0};

int main() {
    size_t sizes[] = {100, 120, 128, 256, 512, 1024};
    int i = 0;
    for (i = 0; i < sizeof(sizes) / sizeof(sizes[0]); i++) {
        size_t size = sizes[i];
        ptr[i] = malloc(size);
        if (ptr == NULL) {
            fprintf(stderr, "malloc failed for size %zu\n", size);
            continue;
        }
        
        print_chunk_info(ptr[i], i);
        // size_t actual_size = malloc_usable_size(ptr[i]);
        // printf("Requested size: %zu, Actual size: %zu\n", size, actual_size);
        printf("    data addr: %p\n", ptr[i]);
        char str[100] = "hello-bruce";
        snprintf(str + strlen(str), sizeof(str) - strlen(str) - 1, "%d", i);
        str[strlen(str)] = 0;
        sscanf(str, "%s", (char *)ptr[i]);
        printf("    ptr[%d]:%s\n", i, (char *)ptr[i]);
    }

    printf("bruce >>> release index:1\n");
    if (ptr[1] != NULL) {
        free(ptr[1]);
        flag[1] = 1;
    }

    for (i = 0; i < 16; i++) {
        if (ptr[i] != NULL) {
            print_chunk_info(ptr[i], i);
            printf("    data addr: %p\n", ptr[i]);
            // if (flag[i] != 1) {
                printf("    ptr[%d]:%s\n", i, (char *)ptr[i]);
                // }
        }

        
    }

    printf("bruce >>> release index:3\n");
    if (ptr[3] != NULL) {
        free(ptr[3]);
        flag[3] = 1;
    }

    for (i = 0; i < 16; i++) {
        if (ptr[i] != NULL) {
            print_chunk_info(ptr[i], i);
            printf("    data addr: %p\n", ptr[i]);
            // if (flag[i] != 1) {
                printf("    ptr[%d]:%s\n", i, (char *)ptr[i]);
                // }
        }
        
    }

    printf("bruce >>> release index:2\n");
    if (ptr[2] != NULL) {
        free(ptr[2]);
        flag[2] = 1;
    }

    for (i = 0; i < 16; i++) {
        if (ptr[i] != NULL) {
            print_chunk_info(ptr[i], i);
            printf("    data addr: %p\n", ptr[i]);
            // if (flag[i] != 1) {
                printf("    ptr[%d]:%s\n", i, (char *)ptr[i]);
                // }
        }
        
    }

    // clear
    printf("bruce >>> clean all\n");
    for (i = 0; i < 16; i++) {
        if (ptr[i] != NULL && flag[i] != 1) {
            free(ptr[i]);
        }
        ptr[i] = NULL;
    }

    // printf("sizeof(size_t)=%lu\n", sizeof(size_t));
    
    return 0;
}